package com.hzncc.flowable_diboot.service.contractmanage.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.diboot.file.entity.FileRecord;
import com.diboot.file.service.FileRecordService;
import com.diboot.iam.util.IamSecurityUtils;
import com.hzncc.flowable_diboot.contract.entity.ContractAudit;
import com.hzncc.flowable_diboot.contract.service.ContractAuditService;
import com.hzncc.flowable_diboot.entity.invoicemanage.InvoiceRegister;
import com.hzncc.flowable_diboot.project_contracts.entity.ProjectContractAudit;
import com.hzncc.flowable_diboot.service.invoicemanage.InvoiceRegisterService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Service;

import com.diboot.core.util.S;
import com.diboot.core.service.impl.BaseServiceImpl;

import com.hzncc.flowable_diboot.entity.contractmanage.ContractDocumentManagement;

import com.hzncc.flowable_diboot.mapper.contractmanage.ContractDocumentManagementMapper;
import com.hzncc.flowable_diboot.service.contractmanage.ContractDocumentManagementService;

import java.time.LocalDateTime;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * 合同文件管理 相关Service实现类
 *
 * @author MyName
 * @version 1.0
 * @date 2024-12-30
 * Copyright © MyCorp
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ContractDocumentManagementServiceImpl extends BaseServiceImpl<ContractDocumentManagementMapper, ContractDocumentManagement> implements ContractDocumentManagementService {

    private final FileRecordService fileRecordService;
    private final ContractAuditService contractAuditService;
    private final InvoiceRegisterService invoiceRegisterService;

    Map<String, String> docTypeMap = Map.of(
            "合同正本", "0",
            "合同传真件", "3",
            "回执单", "1",
            "验收单正本", "2",
            "验收单传真件", "4",
            "收货证明正本", "5",
            "收货证明传真件", "6",
            "中标通知书", "7",
            "补充说明", "8"
    );

    public String extractDocumentType(String fileName) {
        // 去掉文件扩展名
        String nameWithoutExtension = fileName.substring(0, fileName.lastIndexOf('.'));

        // 按下划线分割
        String[] parts = nameWithoutExtension.split("_");

        // 根据格式确定文档类型的位置
        if (parts.length >= 3) {
            return parts[2]; // 文档类型在第三个位置
        } else {
            throw new IllegalArgumentException("文件名格式不正确");
        }
    }


    /**
     * 批量上传文件
     *
     * @param fileIds 文件id
     */
    @Override
    public void batchUploadFiles(String fileIds) {
        // 将文件ID字符串按逗号分割成列表
        List<String> fileIdList = S.splitToList(fileIds, ",");

        // 获取文件记录列表
        List<FileRecord> fileRecords = fileRecordService.getEntityListByIds(fileIdList);
        List<String> illegalName = fileRecords.stream().map(FileRecord::getFileName).filter(e -> {
            String[] s = e.split("_");
            if (s.length == 4){
                return !S.equals(s[2],"回执单");
            }
            return s.length != 3;
        }).toList();
        if (illegalName.size() > 0){
            throw new IllegalArgumentException("文件名格式不正确：" + illegalName);
        }
        // 使用Map来存储合同编码和文档类型对应的ContractDocumentManagement对象
        Map<String, ContractDocumentManagement> contractDocMap = fileRecords.stream()
                .map(fileRecord -> {
                    String baseFileName = FilenameUtils.removeExtension(fileRecord.getFileName());
                    // 解析文件名，获取合同编码、客户名称和文档类型
                    String[] parts = baseFileName.split("_");
                    String contractCode = parts[0];
                    String customerName = parts[1];
                    String docType = docTypeMap.get(extractDocumentType(fileRecord.getFileName()));
                    String invoiceNo = null;
                    // 构建Map的key
                    if("1".equals(docType)){
                        invoiceNo = parts[3];
                    }
                    String key = contractCode + "_" + docType;

                    // 创建或获取ContractDocumentManagement对象
                    ContractDocumentManagement contractDoc = new ContractDocumentManagement()
                            .setContractCode(contractCode)
                            .setCustomerName(customerName)
                            .setFileId(fileRecord.getId())
                            .setFileNum(1L)
                            .setDocType(docType)
                            .setInvoiceNo(invoiceNo);

                    return new AbstractMap.SimpleEntry<>(key, contractDoc);
                })
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (existing, replacement) -> {
                            // 如果已经存在相同合同编号和文档类型的记录，拼接文件ID并增加文件数量
                            existing.setFileId(existing.getFileId() == null ? replacement.getFileId() : existing.getFileId() + "," + replacement.getFileId());
                            existing.setFileNum(existing.getFileNum() == null ? 1 : existing.getFileNum() + 1);
                            return existing;
                        }
                ));

        // 将Map中的ContractDocumentManagement对象转换为列表并保存到数据库
        List<ContractDocumentManagement> contractDocsToSave = new ArrayList<>(contractDocMap.values());
        // 获取已有的合同文件管理记录
        QueryWrapper<ContractDocumentManagement> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("contract_code", contractDocsToSave.stream().map(ContractDocumentManagement::getContractCode).collect(Collectors.toList()));
        List<ContractDocumentManagement> existContract = this.getEntityList(queryWrapper);
        // 合并已有合同号及文件类型并保存到数据库
        for (ContractDocumentManagement exist : existContract) {
            ContractDocumentManagement contractDoc = contractDocMap.get(exist.getContractCode() + "_" + exist.getDocType());
            if (contractDoc != null) {
                contractDoc.setFileId(contractDoc.getFileId() == null ? exist.getFileId() : exist.getFileId() + "," + contractDoc.getFileId());
                contractDoc.setFileNum(contractDoc.getFileNum() == null ? exist.getFileNum() + 1 : exist.getFileNum() + contractDoc.getFileNum());
                contractDoc.setId(exist.getId());
                contractDoc.setCreateTime(exist.getCreateTime());
                contractDoc.setUpdateTime(LocalDateTime.now());
                contractDoc.setCreateBy(exist.getCreateBy());
                contractDoc.setUpdateBy(IamSecurityUtils.getCurrentUserId());
            }
        }
        this.createOrUpdateEntities(contractDocsToSave);
        // 变更合同正本回执状态
        List<String> contractCodeList = contractDocsToSave.stream().filter(e -> S.equals(e.getDocType(), "0")).map(ContractDocumentManagement::getContractCode).toList();
        if (!contractCodeList.isEmpty()) {
            UpdateWrapper<ContractAudit> uw = new UpdateWrapper<>();
            uw.lambda().set(ContractAudit::getContractOriginalRecoveryStatus, "1").in(ContractAudit::getContractCode, contractCodeList);
            contractAuditService.updateEntity(uw);
        }
        List<String> invoiceNoList = contractDocsToSave.stream().filter(e -> S.equals(e.getDocType(), "1")).map(ContractDocumentManagement::getInvoiceNo).toList();
        if (!invoiceNoList.isEmpty()) {
            UpdateWrapper<InvoiceRegister> invoiceRegisterUpdate = new UpdateWrapper<>();
            invoiceRegisterUpdate.lambda().set(InvoiceRegister::getReceipted, "1").set(InvoiceRegister::getReceiptDate,LocalDateTime.now()).in(InvoiceRegister::getInvoiceNo, invoiceNoList);
            invoiceRegisterService.updateEntity(invoiceRegisterUpdate);
        }
    }

    @Override
    public String calculateReceiptRate() {
        Long red = contractAuditService.lambdaQuery().eq(ContractAudit::getContractOriginalRecoveryStatus, "1").eq(ContractAudit::isDeleted, 0).count();
        Long unred = contractAuditService.lambdaQuery().ne(ContractAudit::getContractOriginalRecoveryStatus, "1").eq(ContractAudit::isDeleted, 0).count();
        double rate = red * 100.0 / (red + unred);
        return rate + "%";
    }
}